package com.siteseat.common.foundation;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * TODO: 1. how to avoid data corruption when data may be partially written to
 * disk during write()/flush()? trace file length? 2. rate measuring
 */
public abstract class Daemon extends Actor {

  private ExecutorService executor;

  /**
   * Gets the executor
   * 
   * @return the executor
   */
  public ExecutorService getExecutor() {
    return executor;
  }

  /**
   * Sets the executor
   * 
   * @param executor
   *          the executor to set
   */
  public void setExecutor( ExecutorService executor ) {
    this.executor = executor;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected void doInit() throws Exception {
    ExecutorService pool = getExecutor();
    if( pool == null ) {
      pool = Executors.newFixedThreadPool( 1 );
      setExecutor( pool );
    }
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected void doDestroy() throws Exception {
    shutdownAndAwaitTermination();
  }
  
  /**
   * 
   */
  public void shutdownAndAwaitTermination() {
    ExecutorService pool = getExecutor();
    
    pool.shutdown(); // Disable new tasks from being submitted
    
    try {
      // Wait a while for existing tasks to terminate
      if (!pool.awaitTermination( 1, TimeUnit.SECONDS) ) {
        pool.shutdownNow(); // Cancel currently executing tasks
        // Wait a while for tasks to respond to being cancelled
        if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
            log.error("Pool did not terminate");
        }
      }
    } catch (InterruptedException ie) {
      // (Re-)Cancel if current thread also interrupted
      pool.shutdownNow();
      // Preserve interrupt status
      Thread.currentThread().interrupt();
    }
  }


}
